#include "RectWidgetPipeline.h"

#include "Render/VulkanContext.h"
#include "Render/Material/VulkanShader.h"
#include "Render/Material/VulkanShaders.h"

void SRectWidgetPipeline::Init()
{
    CreatePipelineLayout();
    CreatePipeline();
}

void SRectWidgetPipeline::CreatePipelineLayout()
{
    //create pipeline layout
    vk::PushConstantRange PushConstantRange=vk::PushConstantRange()
        .setStageFlags(vk::ShaderStageFlagBits::eVertex)
        .setOffset(0)
        .setSize(sizeof(CVulkanContext::SRectVertexPushConstant));   

    vk::PipelineLayoutCreateInfo PipelineLayoutCreateInfo=vk::PipelineLayoutCreateInfo()
        .setSetLayoutCount(0)
        .setPushConstantRangeCount(1)
        .setPPushConstantRanges(&PushConstantRange);

    PipelineLayout=CVulkanContext::Get()->GetDevice().createPipelineLayout(PipelineLayoutCreateInfo);
}

void SRectWidgetPipeline::CreatePipeline()
{
    //just use a single color and a z value to draw a rect
    //do not need any descriptor set and vertex buffer

    auto VertexShader=
        CVulkanContext::Get()
        ->GetShaderManager()
        ->GetVulkanOnlyShader(U"RectWidgetVertex");
    auto FragmentShader= 
        CVulkanContext::Get()->GetShaderManager()->
        GetVulkanOnlyShader(U"RectWidgetFragment");
    

    //dynamic state
    vk::DynamicState DynamicState[2]={vk::DynamicState::eViewport,vk::DynamicState::eScissor};

    vk::PipelineDynamicStateCreateInfo PipelineDynamicStateCreateInfo=vk::PipelineDynamicStateCreateInfo()
        .setDynamicStateCount(2)
        .setPDynamicStates(DynamicState);

    vk::PipelineShaderStageCreateInfo PipelineShaderStageCreateInfo[2];
    PipelineShaderStageCreateInfo[0]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eVertex)
        .setModule(VertexShader->Module)
        .setPName("main");

    PipelineShaderStageCreateInfo[1]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eFragment)
        .setModule(FragmentShader->Module)
        .setPName("main");

    vk::PipelineVertexInputStateCreateInfo PipelineVertexInputStateCreateInfo=vk::PipelineVertexInputStateCreateInfo()
        .setVertexBindingDescriptionCount(0)
        .setVertexAttributeDescriptionCount(0);

    vk::PipelineInputAssemblyStateCreateInfo PipelineInputAssemblyStateCreateInfo=vk::PipelineInputAssemblyStateCreateInfo()
        .setTopology(vk::PrimitiveTopology::eTriangleStrip);
    
    vk::PipelineViewportStateCreateInfo PipelineViewportStateCreateInfo=vk::PipelineViewportStateCreateInfo()
        .setViewportCount(1)
        .setScissorCount(1);

    vk::PipelineRasterizationStateCreateInfo PipelineRasterizationStateCreateInfo=vk::PipelineRasterizationStateCreateInfo()
        .setPolygonMode(vk::PolygonMode::eFill)
        .setCullMode(vk::CullModeFlagBits::eNone)
        .setFrontFace(vk::FrontFace::eClockwise)
        .setLineWidth(1.0f);

    vk::PipelineMultisampleStateCreateInfo PipelineMultisampleStateCreateInfo=vk::PipelineMultisampleStateCreateInfo()
        .setRasterizationSamples(vk::SampleCountFlagBits::e1);

    vk::PipelineDepthStencilStateCreateInfo PipelineDepthStencilStateCreateInfo=vk::PipelineDepthStencilStateCreateInfo()
        .setDepthTestEnable(true)
        .setDepthWriteEnable(true)
        .setDepthCompareOp(vk::CompareOp::eLessOrEqual)
        .setDepthBoundsTestEnable(false)
        .setStencilTestEnable(false);

    vk::PipelineColorBlendAttachmentState PipelineColorBlendAttachmentState=vk::PipelineColorBlendAttachmentState()

        .setColorWriteMask(
            vk::ColorComponentFlagBits::eR
            |vk::ColorComponentFlagBits::eG
            |vk::ColorComponentFlagBits::eB
            |vk::ColorComponentFlagBits::eA
        )
        .setBlendEnable(true) //color might be transparent
        .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha)
        .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha)
        .setColorBlendOp(vk::BlendOp::eAdd)
        .setSrcAlphaBlendFactor(vk::BlendFactor::eZero)
        .setDstAlphaBlendFactor(vk::BlendFactor::eOne)
        .setAlphaBlendOp(vk::BlendOp::eAdd)
        ; 

    vk::PipelineColorBlendStateCreateInfo PipelineColorBlendStateCreateInfo=vk::PipelineColorBlendStateCreateInfo()
        .setAttachmentCount(1)
        .setPAttachments(&PipelineColorBlendAttachmentState);

    vk::GraphicsPipelineCreateInfo GraphicsPipelineCreateInfo=vk::GraphicsPipelineCreateInfo()
        .setPDynamicState(&PipelineDynamicStateCreateInfo)
        .setStageCount(2)
        .setPStages(PipelineShaderStageCreateInfo)
        .setPVertexInputState(&PipelineVertexInputStateCreateInfo)
        .setPInputAssemblyState(&PipelineInputAssemblyStateCreateInfo)
        .setPViewportState(&PipelineViewportStateCreateInfo)
        .setPRasterizationState(&PipelineRasterizationStateCreateInfo)
        .setPMultisampleState(&PipelineMultisampleStateCreateInfo)
        .setPDepthStencilState(&PipelineDepthStencilStateCreateInfo)
        .setPColorBlendState(&PipelineColorBlendStateCreateInfo)
        .setLayout(PipelineLayout)
        .setRenderPass(CVulkanContext::Get()->GetWidgetRenderPass())
        .setSubpass(0);

    Pipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;
 

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Rect_LeftTop_frag")->Module);
    LeftTopCornerPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Rect_RightTop_frag")->Module);
    RightTopCornerPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Rect_LeftBottom_frag")->Module);
    LeftBottomCornerPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Rect_RightBottom_frag")->Module);
    RightBottomCornerPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Border_LeftTop_frag")->Module);
    LeftTopCornerBorderPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Border_RightTop_frag")->Module);
    RightTopCornerBorderPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Border_LeftBottom_frag")->Module);
    LeftBottomCornerBorderPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

    PipelineShaderStageCreateInfo[1].setModule(CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"Border_RightBottom_frag")->Module);
    RightBottomCornerBorderPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;
}
